package models

import (
	"gitee.com/sansaniot/ssiot-core/httpmvc/model"
	"gitee.com/sansaniot/ssiot-core/logger"

	cDto "ssalarm/common/dto"
	"ssalarm/common/utils"
	"ssalarm/internal/alarm/models/query"
)

type SysAlarm struct {
	Id            string          `json:"id" gorm:"primaryKey"`
	DevSn         string          `json:"devSn"`
	VarKey        string          `json:"varKey"`
	VarName       string          `json:"varName"`
	VarValue      string          `json:"varValue"`
	Level         int             `json:"level"`
	ProcessStatus bool            `json:"processStatus"`
	AlarmTime     *cDto.LocalTime `json:"alarmTime"`
	AlarmType     string          `json:"alarmType"`
	DeptId        string          `json:"deptId"`
	Reason        string          `json:"reason"`
	Suggestion    string          `json:"suggestion"`
	CreateTime    *cDto.LocalTime `json:"createTime"`
	UpdateTime    *cDto.LocalTime `json:"updateTime"`
	AlarmMode     int             `json:"alarmMode"`
	DevType       string          `json:"devType"`

	model.Model

	DevName  string                   `json:"devName" gorm:"-"`
	Warning  []map[string]interface{} `json:"warning"  gorm:"-"`
	DeptName string                   `json:"deptName" gorm:"-"`
}

func (SysAlarm) TableName() string {
	return "sys_alarm"
}

func (e *SysAlarm) Generate() interface{} {
	o := *e
	return &o
}

func (e *SysAlarm) GetId() interface{} {
	return e.Id
}

func (e *SysAlarm) FindAlarmList(req *query.SysAlarmQuery) (err error, result interface{}) {
	list := make([]SysAlarm, 0)
	var count int64
	if req.PageIndex > 0 && req.PageSize > 0 {
		err = e.FindPage(&list, &count,
			cDto.MakeCondition(req.GetNeedSearch()),
			cDto.OrderDest("create_time", true, req.OrderBy),
			cDto.Paginate(req.GetPageSize(), req.GetPageIndex()),
		)
		result = &cDto.Page{
			Records:   list,
			Total:     count,
			PageSize:  req.GetPageSize(),
			PageIndex: req.GetPageIndex(),
			Pages:     (count + int64(req.GetPageSize()) - 1) / int64(req.GetPageSize()),
			Other:     nil,
		}
	} else {
		err = e.FindList(&list,
			cDto.MakeCondition(req.GetNeedSearch()),
			cDto.OrderDest("create_time", true, req.OrderBy),
		)
		result = list
	}
	snList := make([]string, 0)
	keyList := make([]string, 0)
	for _, alarm := range list {
		if !utils.StrIn(alarm.DevSn, snList) {
			snList = append(snList, alarm.DevSn)
		}
		if !utils.StrIn(alarm.VarKey, keyList) {
			keyList = append(keyList, alarm.VarKey)
		}
	}
	// 扩展名称
	deviceName, _, devKeyName := getFieldName(e.Orm, snList)
	// 告警配置
	ac := &SysAlarmConfig{}
	ac.Orm = e.Orm
	aclist := make([]SysAlarmConfig, 0)
	if err = ac.FindList(&aclist, cDto.MakeCondition(query.SysAlarmConfigQuery{SnIn: snList, KeyIn: keyList})); err != nil {
		return
	}
	devKeyWarnMap := make(map[string][]map[string]interface{})
	for _, alarmConfig := range aclist {
		devKeyWarnMap[alarmConfig.DevSn+"#"+alarmConfig.Key] = utils.BytesToMapArr(alarmConfig.Warning)
	}
	if req.PageIndex > 0 && req.PageSize > 0 {
		for i := range list {
			list[i].DevName = deviceName[list[i].DevSn]
			if m, ok := devKeyName[list[i].DevSn]; ok {
				list[i].VarName = m[list[i].VarKey]
			}
			if w, ok := devKeyWarnMap[list[i].DevSn+"#"+list[i].VarKey]; ok {
				list[i].Warning = w
			}
		}
		groupIdName, _ := utils.GroupIdName(e.Orm)
		for i := range list {
			if len(list[i].DeptId) > 0 {
				if deptName, ok := groupIdName[list[i].DeptId]; ok {
					list[i].DeptName = deptName
				}
			}
		}
		result = &cDto.Page{
			Records:   list,
			Total:     count,
			PageSize:  req.GetPageSize(),
			PageIndex: req.GetPageIndex(),
			Pages:     (count + int64(req.GetPageSize()) - 1) / int64(req.GetPageSize()),
			Other:     nil,
		}
	} else {
		for i := range list {
			list[i].DevName = deviceName[list[i].DevSn]
			if m, ok := devKeyName[list[i].DevSn]; ok {
				list[i].VarName = m[list[i].VarKey]
			}
			if w, ok := devKeyWarnMap[list[i].DevSn+"#"+list[i].VarKey]; ok {
				list[i].Warning = w
			}
		}
		groupIdName, _ := utils.GroupIdName(e.Orm)
		for i := range list {
			if len(list[i].DeptId) > 0 {
				if deptName, ok := groupIdName[list[i].DeptId]; ok {
					list[i].DeptName = deptName
				}
			}
		}
		result = list
	}
	return
}

func (e *SysAlarm) CurrentAlarmSns() []string {
	var alarmList []SysAlarm
	var alarmSns []string
	if err := e.Orm.Model(&alarmList).Scopes(cDto.MakeCondition(query.SysAlarmQuery{ProcessNotDone: true})).Distinct().Pluck("dev_sn", &alarmSns).Error; err != nil {
		logger.Error(err)
	}
	return alarmSns
}

func (e *SysAlarm) AutoDoneAlarmList(list []SysAlarm) {
	for _, item := range list {
		e.Orm.Model(e).
			Where("dev_sn = ? and var_key = ? and level = ?", item.DevSn, item.VarKey, item.Level).
			Where("alarm_mode = ?", item.AlarmMode).
			Update("process_status", true)
	}
	logger.Info("告警恢复记录更新", len(list))
}
